﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;

namespace Snowdreamist.Reflection
{
    public static class GenericUtility
    {
        #region generic method

        public static MethodInfo MakeGenericMethodWithOneGenericParameter(MethodInfo method, Type genericType)
        {
            if (method == null)
                throw new ArgumentNullException("method");
            if (!method.IsGenericMethod)
                throw new InvalidOperationException("Method " + method.Name + " isn't a generic method");
            if (genericType == null)
                throw new ArgumentNullException("genericType");

            return method.MakeGenericMethod(genericType);
        }

        public static object InvokeGenericMethodWithOneGenericParameter(object instance, MethodInfo method, Type genericType, params object[] parameters)
        {
            if (method == null)
                throw new ArgumentNullException("method");
            if (!method.IsGenericMethod)
                throw new InvalidOperationException("Method " + method.Name + " isn't a generic method");
            if (genericType == null)
                throw new ArgumentNullException("genericType");

            var genericMethod = method.MakeGenericMethod(genericType);
            return genericMethod.Invoke(instance, parameters);
        }

        public static object InvokeGenericMethodWithOneGenericParameter(Type classType, object instance, string methodName, Type genericType, params object[] parameters)
        {
            if (classType == null)
                throw new ArgumentNullException("classType");
            if (string.IsNullOrWhiteSpace(methodName))
                throw new ArgumentNullException("Invalid method name");
            if (genericType == null)
                throw new ArgumentNullException("genericType");

            MethodInfo method = null;

            if (instance != null)
                method = classType.GetMethod(methodName);
            else
                method = classType.GetMethod(methodName, BindingFlags.Static);

            return InvokeGenericMethodWithOneGenericParameter(instance, method, genericType, parameters);
        }

        #endregion generic method
    }
}